package info.thereisonlywe.onenesspathfinder.ui;

import info.thereisonlywe.core.project.ProjectConstants;
import info.thereisonlywe.core.project.ProjectLocalization;
import info.thereisonlywe.core.toolkit.StringToolkit;
import info.thereisonlywe.core.toolkit.TableScrollingToolkit;
import info.thereisonlywe.core.toolkit.ThreadToolkit;
import info.thereisonlywe.onenesspathfinder.controllers.RecitationController;
import info.thereisonlywe.onenesspathfinder.launcher.Main;
import info.thereisonlywe.quran.Quran;
import info.thereisonlywe.quran.QuranicVerse;
import info.thereisonlywe.quran.bookmark.QuranicBookmark;
import info.thereisonlywe.quran.bookmark.QuranicBookmarkList;
import info.thereisonlywe.salat.recitation.reciter.Reciter;
import info.thereisonlywe.salat.recitation.reciter.ReciterList;

import java.awt.Frame;
import java.awt.Toolkit;
import java.awt.TrayIcon.MessageType;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.table.AbstractTableModel;

/**
 * @author thereisonlywe
 * 
 *         We access UI features via this class
 */

public class UIDelegate {

	private static Timer sectionChangeTimer = null;
	protected static int fontSize = Main.runtimeSettings
			.getStringAsInt("font.size");
	protected static Reciter quranReciter = ReciterList
			.getReciterByName(Main.runtimeSettings
					.getString("recitation.reciter"));
	protected static Reciter textReciter = ReciterList
			.getReciterByName(Main.runtimeSettings
					.getString("recitation.textreciter"));
	protected static int volume = Main.runtimeSettings.getStringAsInt("volume");
	protected static boolean loop = Main.runtimeSettings
			.getStringAsBoolean("recitation.loop");

	public static Reciter getQuranReciter()
	{
		return quranReciter;
	}

	public static Reciter getTextReciter()
	{
		return textReciter;
	}

	public static int getVolume()
	{
		return volume;
	}

	public static boolean getLoop()
	{
		return loop;
	}

	public static class SectionPaneHook {

		public static class ResetTask extends SwingWorker<String, Object> {

			@Override
			public String doInBackground()
			{
				((SectionPane.TableModel) MainFrame.view_Browser
						.getSectionPane().getTable().getModel())
						.fireTableDataChanged();
				return null;
			}

			@Override
			protected void done()
			{
				ThreadToolkit.sleep(500);
				UIDelegate.SectionPaneHook.focusRow(UIDelegate
						.getDisplayedVerse().getVerseNumber() - 1);
			}
		}

		public static class RefreshTask extends SwingWorker<String, Object> {

			private int index = 0;

			public RefreshTask(int i)
			{
				index = i;
			}

			@Override
			public String doInBackground()
			{
				((SectionPane.TableModel) MainFrame.view_Browser
						.getSectionPane().getTable().getModel())
						.fireTableRowsUpdated(index, index);
				return null;
			}

			@Override
			protected void done()
			{
				UIDelegate.SectionPaneHook.focusRow(UIDelegate
						.getDisplayedVerse().getVerseNumber() - 1);
			}
		}

		public static void refresh()
		{
			((AbstractTableModel) MainFrame.view_Browser.getSectionPane()
					.getTable().getModel()).fireTableDataChanged();
			MainFrame.view_Browser.getSectionPane().getTable().repaint();
		}

		public static void focusRow(final int rowIndex)
		{
			MainFrame.view_Browser.getSectionPane().getTable()
					.getSelectionModel()
					.setSelectionInterval(rowIndex, rowIndex);
			TableScrollingToolkit.centerCell(MainFrame.view_Browser
					.getSectionPane().getTable(), rowIndex, 0);
		}

	}

	public static class BookmarkPaneHook {

		private final static QuranicBookmarkList bookmarks = new QuranicBookmarkList();

		public static void addBookmarkWindow()
		{
			UIDelegate.setOpenDialog(true);
			final String bc = JOptionPane.showInputDialog(null,
					ProjectLocalization.getString(
							ProjectConstants.ONENESS_PATHFINDER_PROJECT,
							"Bookmark.Comment"), "Oneness Pathfinder",
					JOptionPane.PLAIN_MESSAGE);
			if (bc == null) { return; }
			// change bookmark info if bookmark already exists
			final boolean changed = bookmarks
					.setBookmarkInfo(new QuranicBookmark(UIDelegate
							.getDisplayedVerse(), bc));
			if (!changed)
			{
				addDisplayedVerseToBookmarks(bc);
			}
			UIDelegate.setOpenDialog(false);
		}

		public static void addDisplayedVerseToBookmarks(String info)
		{
			final QuranicVerse v = UIDelegate.getDisplayedVerse();
			if (bookmarks.addBookmark(new QuranicBookmark(v, info)))
			{
				refresh();
				final int order = bookmarks.getOrder(v);
				UIDelegate.BookmarkPaneHook.selectRowIndices(order, order);
			}
		}

		public static QuranicBookmarkList getBookmarkList()
		{
			return bookmarks;
		}

		public static QuranicBookmark[] getSelected()
		{
			final int indices[] = UIDelegate.BookmarkPaneHook
					.getSelectedRowIndices();
			final QuranicBookmark b[] = new QuranicBookmark[indices.length];
			for (int i = 0; i < indices.length; i++)
			{
				b[i] = bookmarks.getBookmark(indices[i]);
			}
			return b;
		}

		public static int[] getSelectedRowIndices()
		{
			return MainFrame.view_Windows.getBookmarkPane().getTable()
					.getSelectedRows();
		}

		public static void refresh()
		{
			((AbstractTableModel) MainFrame.view_Windows.getBookmarkPane()
					.getTable().getModel()).fireTableDataChanged();
			MainFrame.view_Windows.getBookmarkPane().getTable().repaint();
		}

		public static void removeDisplayedVerseFromBookmarks()
		{
			if (bookmarks.removeFromBookmarks(new QuranicBookmark(UIDelegate
					.getDisplayedVerse(), "")))
			{
				refresh();
			}
		}

		public static void removeSelectedBookmarks()
		{
			final int indices[] = UIDelegate.BookmarkPaneHook
					.getSelectedRowIndices();
			boolean found = false;
			for (int i = 0; i < indices.length; i++)
			{
				final QuranicVerse v = bookmarks.getBookmark(indices[i] - i)
						.getPosition();
				final QuranicVerse dv = UIDelegate.getDisplayedVerse();
				if (!found && v.equals(dv))
				{
					found = true;
				}
				bookmarks.removeFromBookmarks(indices[i] - i, false);
			}
			refresh();
		}

		public static void selectAll()
		{
			MainFrame.view_Windows
					.getBookmarkPane()
					.getTable()
					.getSelectionModel()
					.setSelectionInterval(0,
							bookmarks.getNumberOfBookmarks() - 1);
		}

		public static void selectRowIndices(int indexStart, int indexEnd)
		{
			MainFrame.view_Windows.getBookmarkPane().getTable()
					.getSelectionModel()
					.setSelectionInterval(indexStart, indexEnd);
		}

	}

	public static class VersePaneHook {

		public static void refresh()
		{
			((AbstractTableModel) MainFrame.view_Browser.getVersePane()
					.getTable().getModel()).fireTableDataChanged();
			MainFrame.view_Browser.getVersePane().getTable().repaint();
		}
	}

	public static class NavigationBarHook {

		private static int lastState;

		public synchronized static void switchRecitationState(final int state)
		{
			if (!isFrameVisible() || lastState == state) return;
			SwingUtilities.invokeLater(new Runnable()
			{
				@Override
				public void run()
				{
					switch (state)
					{
					case (0):
						MainFrame.view_Navigation.button_Stop.setIcon(new ImageIcon(
								NavigationBar.class
										.getResource("/info/thereisonlywe/onenesspathfinder/resources/icons/stop.png")));
						break;
					case (1):
						MainFrame.view_Navigation.button_Stop.setIcon(new ImageIcon(
								NavigationBar.class
										.getResource("/info/thereisonlywe/onenesspathfinder/resources/icons/stop_yellow.png")));
						break;
					case (2):
						MainFrame.view_Navigation.button_Stop.setIcon(new ImageIcon(
								NavigationBar.class
										.getResource("/info/thereisonlywe/onenesspathfinder/resources/icons/stop_red.png")));
						break;
					}
					lastState = state;
					MainFrame.view_Navigation.button_Stop.repaint();
				}
			});
		}

	}

	private static boolean fullScreen = false;

	private static boolean openDialog = false;

	public static long lastOpenDialog = 0;

	private static int currentVerseIndex = 0;

	private static boolean browserLock;

	public static void decreaseVolume()
	{
		if (volume == 0)
		{
			Toolkit.getDefaultToolkit().beep();
		}
		else if (volume < 10)
		{
			volume = 0;
		}
		else
		{
			volume -= 10;
		}
		RecitationController.getImam().setVolume(volume);
	}

	public static void disEngageBrowserLock()
	{
		browserLock = false;
	}

	public static void disposeFrame()
	{
		MainFrame.frame.dispose();
	}

	public static void engageBrowserLock()
	{
		browserLock = true;
	}

	public static QuranicVerse getDisplayedVerse()
	{
		return Quran.getVerse(currentVerseIndex);
	}

	public static int getDisplayedVerseIndex()
	{
		return currentVerseIndex;
	}

	public static int getQuranFontSize()
	{
		switch (fontSize)
		{
		case 0:
			return 24;
		case 1:
			return 36;
		case 2:
			return 52;
		case 3:
			return 104;
		case 4:
			return 164;
		case 5:
			return 304;
		default:
			return 52;
		}
	}

	public static int getSectionIndex()
	{
		return NavigationBar.comboBox_Section.getSelectedIndex();
	}

	public static int getTextFontSize()
	{
		switch (fontSize)
		{
		case 0:
			return 14;
		case 1:
			return 18;
		case 2:
			return 22;
		case 3:
			return 52;
		case 4:
			return 106;
		case 5:
			return 196;
		default:
			return 22;
		}
	}

	public static int getVerseIndex()
	{
		return NavigationBar.comboBox_Verse.getSelectedIndex();
	}

	public static void increaseVolume()
	{
		if (volume == 100)
		{
			Toolkit.getDefaultToolkit().beep();
		}
		else if (volume > 90)
		{
			volume = 100;
		}
		else
		{
			volume += 10;
		}
		RecitationController.getImam().setVolume(volume);
	}

	public static boolean isBrowserLocked()
	{
		return browserLock;
	}

	public static boolean isFrameVisible()
	{
		return MainFrame.frame.isVisible();
	}

	public static boolean isDialogOpen()
	{
		if (System.currentTimeMillis() - lastOpenDialog < 250)
		{
			return true;
		}
		else
		{
			if (openDialog)
			{
				return openDialog;
			}
			else
			{
				return RecitationController.getImam().isDialogOpen();
			}
		}
	}

	public static void refreshSection()
	{
		if (isFrameVisible())
		{
			SwingUtilities.invokeLater(new Runnable()
			{
				@Override
				public void run()
				{
					setSection();
				}
			});
		}

		else
		{
			setSection();
		}
	}

	public static void refreshSectionAndResetVerse()
	{
		if (isFrameVisible())
		{
			SwingUtilities.invokeLater(new Runnable()
			{
				@Override
				public void run()
				{
					setSectionAndResetVerse();
				}
			});
		}

		else
		{
			setSectionAndResetVerse();
		}
	}

	public static void refreshVerse()
	{
		if (isFrameVisible())
		{
			SwingUtilities.invokeLater(new Runnable()
			{
				@Override
				public void run()
				{
					setVerse();
				}
			});
		}

		else
		{
			setVerse();
		}
	}

	public static void saveSettings()
	{
		Main.runtimeSettings.set("navigation.font.size", fontSize);
		Main.runtimeSettings.set("recitation.loop", loop);
		Main.runtimeSettings.set("recitation.reciter", quranReciter.getName());
		Main.runtimeSettings.set("recitation.textreciter",
				textReciter != null ? textReciter.getName() : "");
		Main.runtimeSettings.set("scratchpad.text", MainFrame.view_Windows
				.getScratchPanel().getText());
		Main.runtimeSettings.set("section", getDisplayedVerse()
				.getSectionNumber());
		Main.runtimeSettings.set("verse", getDisplayedVerse().getVerseNumber());
		Main.runtimeSettings.set("volume", volume);
		Main.runtimeSettings.set("mushaf", Quran.getMushaf());
		Main.runtimeSettings.write();
	}

	public static void seekToFirstVerseInSection()
	{
		NavigationBar.comboBox_Verse.setSelectedIndex(0);
	}

	public static void seekToLastVerseInSection()
	{
		NavigationBar.comboBox_Verse
				.setSelectedIndex(NavigationBar.comboBox_Verse.getItemCount() - 1);
	}

	public static boolean seekToNextSection()
	{
		if ((!UIDelegate.isBrowserLocked() || RecitationController.getImam()
				.isPaused())
				&& NavigationBar.comboBox_Section.getSelectedIndex() + 1 != NavigationBar.comboBox_Section
						.getItemCount())
		{
			NavigationBar.comboBox_Section
					.setSelectedIndex(NavigationBar.comboBox_Section
							.getSelectedIndex() + 1);
			return true;
		}
		else
		{
			Toolkit.getDefaultToolkit().beep();
			return false;
		}
	}

	public static boolean seekToNextVerse()
	{
		if ((!UIDelegate.isBrowserLocked() || RecitationController.getImam()
				.isPaused())
				&& NavigationBar.comboBox_Verse.getSelectedIndex() + 1 != NavigationBar.comboBox_Verse
						.getItemCount())
		{
			NavigationBar.comboBox_Verse
					.setSelectedIndex(NavigationBar.comboBox_Verse
							.getSelectedIndex() + 1);
			return true;
		}
		else
		{
			Toolkit.getDefaultToolkit().beep();
			return false;
		}
	}

	public static boolean seekToPreviousSection()
	{
		if ((!UIDelegate.isBrowserLocked() || RecitationController.getImam()
				.isPaused())
				&& NavigationBar.comboBox_Section.getSelectedIndex() != 0)
		{
			NavigationBar.comboBox_Section
					.setSelectedIndex(NavigationBar.comboBox_Section
							.getSelectedIndex() - 1);
			return true;
		}
		else
		{
			Toolkit.getDefaultToolkit().beep();
			return false;
		}
	}

	public static boolean seekToPreviousVerse()
	{
		if ((!UIDelegate.isBrowserLocked() || RecitationController.getImam()
				.isPaused())
				&& NavigationBar.comboBox_Verse.getSelectedIndex() != 0)
		{
			NavigationBar.comboBox_Verse
					.setSelectedIndex(NavigationBar.comboBox_Verse
							.getSelectedIndex() - 1);
			// DisplayController.refreshVerse();
			return true;
		}
		else
		{
			Toolkit.getDefaultToolkit().beep();
			return false;
		}
	}

	public static void seekToVerse(final QuranicVerse v)
	{
		boolean sc = false;
		if (NavigationBar.comboBox_Section.getSelectedIndex() != v
				.getSectionNumber() - 1)
		{
			NavigationBar.comboBox_Section.setSelectedIndex(v
					.getSectionNumber() - 1);
			sc = true;
		}
		if (sc)
		{
			UIDelegate.refreshSection();
		}
		if (sc
				|| v.getVerseNumber() - 1 != NavigationBar.comboBox_Verse
						.getSelectedIndex())
		{
			if (isFrameVisible())
			{
				SwingUtilities.invokeLater(new Runnable()
				{
					@Override
					public void run()
					{
						NavigationBar.comboBox_Verse.setSelectedIndex(v
								.getVerseNumber() - 1);
					}
				});
			}

			else
			{
				NavigationBar.comboBox_Verse.setSelectedIndex(v
						.getVerseNumber() - 1);
			}
			UIDelegate.refreshVerse();
		}
	}

	public static boolean seekToVerseInSection(int x)
	{
		if (x <= Quran.getInSectionVerseCount(UIDelegate.getDisplayedVerse()
				.getSectionNumber()))
		{
			NavigationBar.comboBox_Verse.setSelectedIndex(x - 1);
			return true;
		}
		return false;
	}

	public static void setDisplayedVerseIndex(int index)
	{
		currentVerseIndex = index;
	}

	public static void setFrameVisibility(boolean val)
	{
		MainFrame.frame.setVisible(val);
	}

	protected static void setOpenDialog(boolean val)
	{
		openDialog = val;
		if (val == false)
		{
			lastOpenDialog = System.currentTimeMillis();
		}
	}

	public static void showFrame()
	{
		MainFrame.frame.setVisible(true);
		MainFrame.frame.setExtendedState(Frame.MAXIMIZED_BOTH);
		MainFrame.frame.requestFocus();
	}

	public static void showInformationDialog(String dialogKey)
	{
		openDialog = true;
		JOptionPane.showOptionDialog(null,
				StringToolkit.multiLine(
						ProjectLocalization.getString(
								ProjectConstants.ONENESS_PATHFINDER_PROJECT,
								dialogKey), UIConstants.MAX_CHARS_PER_LINE),
				"Oneness Pathfinder", JOptionPane.DEFAULT_OPTION,
				JOptionPane.INFORMATION_MESSAGE, null, null, null);
		openDialog = false;
	}

	public static void toggleFullScreen()
	{
		if (fullScreen)
		{
			MainFrame.frame.setVisible(false);
			MainFrame.frame.dispose();
			MainFrame.frame.setUndecorated(false);
			MainFrame.frame.setVisible(true);
			fullScreen = !fullScreen;
		}
		else
		{
			MainFrame.frame.setVisible(false);
			MainFrame.frame.dispose();
			MainFrame.frame.setExtendedState(Frame.MAXIMIZED_BOTH);
			MainFrame.frame.setUndecorated(true);
			MainFrame.frame.setVisible(true);
			fullScreen = !fullScreen;
		}
	}

	public static void setSection()
	{
		final int selectedSectionIndex = NavigationBar.comboBox_Section
				.getSelectedIndex();
		final int tmp = NavigationBar.comboBox_Verse.getSelectedIndex();
		if (selectedSectionIndex + 1 == UIDelegate.getDisplayedVerse()
				.getSectionNumber() && tmp == 1) { return; }
		int currentIndex = 0;
		final int totalverses = Quran
				.getInSectionVerseCount(selectedSectionIndex + 1);
		if (tmp != -1 && tmp < totalverses)
		{
			currentIndex = tmp;
		}
		NavigationBar.comboBox_Verse.removeAllItems();
		for (int i = 1; i <= totalverses; i++)
		{
			NavigationBar.comboBox_Verse.addItem(i);
		}
		NavigationBar.comboBox_Verse.setSelectedIndex(currentIndex);
		UIDelegate.updateVerseIndex();
		Runnable updateSectionInfo = new Runnable()
		{

			@Override
			public void run()
			{
				((SectionPane.TableModel) MainFrame.view_Browser
						.getSectionPane().getTable().getModel()).setSection(
						Quran.getVerse(selectedSectionIndex + 1, 1).getIndex(),
						totalverses);
				NavigationBar.comboBox_Section
						.setToolTipText(NavigationBar.sectionDetails[NavigationBar.comboBox_Section
								.getSelectedIndex()]);
			}
		};
		new Thread(updateSectionInfo).start();
	}

	private static void setSectionAndResetVerse()
	{
		if (sectionChangeTimer == null)
		{
			sectionChangeTimer = new Timer();
			sectionChangeTimer.schedule(new TimerTask()
			{
				@Override
				public void run()
				{
					if (!UIDelegate.isBrowserLocked()
							|| RecitationController.getImam().isPaused())

					{
						NavigationBar.comboBox_Verse.setSelectedIndex(0);
						setSection();
						setVerse();
					}
				}
			}, 250);
		}
		else
		{
			sectionChangeTimer.cancel();
			sectionChangeTimer = null;
			Runnable refresh = new Runnable()
			{
				@Override
				public void run()
				{
					ThreadToolkit.sleep(250);
					setSectionAndResetVerse();
				}
			};
			new Thread(refresh).start();
		}
	}

	private static void setVerse()
	{

		final QuranicVerse v = UIDelegate.getDisplayedVerse();
		final QuranicVerse nV = Quran.getVerse(UIDelegate
				.getDisplayedVerseIndex()
				+ NavigationBar.comboBox_Verse.getSelectedIndex()
				+ 1
				- v.getVerseNumber());
		final int dif = nV.getIndex() - UIDelegate.getDisplayedVerseIndex();
		// if (dif == 0 && UIDelegate.isBrowserLocked())
		// {
		// return;
		// }
		if (dif > 25)
		{
			new UIDelegate.SectionPaneHook.RefreshTask(nV.getVerseNumber() - 1)
					.execute();
		}
		final int NVI = v.getVerseNumber() - 1 + dif;
		UIDelegate.setDisplayedVerseIndex(nV.getIndex());
		if (NavigationBar.comboBox_Verse.getItemCount() == 0)
		{
			UIDelegate.refreshSection();
		}
		((AbstractTableModel) MainFrame.view_Browser.getVersePane().getTable()
				.getModel()).fireTableDataChanged();
		if (MainFrame.view_Windows.isBookmarksWindowMounted())
		{
			final int bi = BookmarkPaneHook.getBookmarkList().getOrder(nV);
			if (bi >= 0)
			{
				MainFrame.view_Windows.getBookmarkPane().getTable()
						.getSelectionModel().setSelectionInterval(bi, bi);
			}
			else
			{
				MainFrame.view_Windows.getBookmarkPane().getTable()
						.getSelectionModel().clearSelection();
			}
		}
		if (NVI >= 0 && nV.getSectionNumber() == v.getSectionNumber())
		{
			UIDelegate.SectionPaneHook.focusRow(NVI);
		}
	}

	private static void updateVerseIndex()
	{
		currentVerseIndex = Quran.getVerse(getSectionIndex() + 1,
				getVerseIndex() + 1).getIndex();
	}

	public static int showConfirmDialog(String dialogKey)
	{
		openDialog = true;
		int val = JOptionPane.showConfirmDialog(null,
				StringToolkit.multiLine(
						ProjectLocalization.getString(
								ProjectConstants.ONENESS_PATHFINDER_PROJECT,
								dialogKey), UIConstants.MAX_CHARS_PER_LINE),
				"Oneness Pathfinder", JOptionPane.YES_NO_OPTION);
		openDialog = false;
		return val;
	}

	public static void showErrorDialog(String dialogKey)
	{
		openDialog = true;
		JOptionPane.showOptionDialog(null,
				StringToolkit.multiLine(
						ProjectLocalization.getString(
								ProjectConstants.ONENESS_PATHFINDER_PROJECT,
								dialogKey), UIConstants.MAX_CHARS_PER_LINE),
				"Oneness Pathfinder", JOptionPane.DEFAULT_OPTION,
				JOptionPane.ERROR_MESSAGE, null, null, null);
		openDialog = false;
	}

	public static void showTrayMessage(String header, String message,
			MessageType type)
	{
		if (Tray.getTrayIcon() != null)
		{
			Tray.getTrayIcon().displayMessage(header, message, type);
		}
	}

	public static void showWarningDialog(String dialogKey)
	{
		openDialog = true;
		JOptionPane.showOptionDialog(null,
				StringToolkit.multiLine(
						ProjectLocalization.getString(
								ProjectConstants.ONENESS_PATHFINDER_PROJECT,
								dialogKey), UIConstants.MAX_CHARS_PER_LINE),
				"Oneness Pathfinder", JOptionPane.DEFAULT_OPTION,
				JOptionPane.WARNING_MESSAGE, null, null, null);
		openDialog = false;
	}

}
